{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Imputing missing values before building an estimator\n\n\nMissing values can be replaced by the mean, the median or the most frequent\nvalue using the basic :class:`sklearn.impute.SimpleImputer`.\nThe median is a more robust estimator for data with high magnitude variables\nwhich could dominate results (otherwise known as a 'long tail').\n\nWith ``KNNImputer``, missing values can be imputed using the weighted\nor unweighted mean of the desired number of nearest neighbors.\n\nAnother option is the :class:`sklearn.impute.IterativeImputer`. This uses\nround-robin linear regression, treating every variable as an output in\nturn. The version implemented assumes Gaussian (output) variables. If your\nfeatures are obviously non-Normal, consider transforming them to look more\nNormal so as to potentially improve performance.\n\nIn addition of using an imputing method, we can also keep an indication of the\nmissing information using :func:`sklearn.impute.MissingIndicator` which might\ncarry some information.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "print(__doc__)\n\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# To use the experimental IterativeImputer, we need to explicitly ask for it:\nfrom sklearn.experimental import enable_iterative_imputer  # noqa\nfrom sklearn.datasets import load_diabetes\nfrom sklearn.datasets import load_boston\nfrom sklearn.ensemble import RandomForestRegressor\nfrom sklearn.pipeline import make_pipeline, make_union\nfrom sklearn.impute import (\n    SimpleImputer, KNNImputer, IterativeImputer, MissingIndicator)\nfrom sklearn.model_selection import cross_val_score\n\nrng = np.random.RandomState(0)\n\nN_SPLITS = 5\nREGRESSOR = RandomForestRegressor(random_state=0)\n\n\ndef get_scores_for_imputer(imputer, X_missing, y_missing):\n    estimator = make_pipeline(\n        make_union(imputer, MissingIndicator(missing_values=0)),\n        REGRESSOR)\n    impute_scores = cross_val_score(estimator, X_missing, y_missing,\n                                    scoring='neg_mean_squared_error',\n                                    cv=N_SPLITS)\n    return impute_scores\n\n\ndef get_results(dataset):\n    X_full, y_full = dataset.data, dataset.target\n    n_samples = X_full.shape[0]\n    n_features = X_full.shape[1]\n\n    # Estimate the score on the entire dataset, with no missing values\n    full_scores = cross_val_score(REGRESSOR, X_full, y_full,\n                                  scoring='neg_mean_squared_error',\n                                  cv=N_SPLITS)\n\n    # Add missing values in 75% of the lines\n    missing_rate = 0.75\n    n_missing_samples = int(np.floor(n_samples * missing_rate))\n    missing_samples = np.hstack((np.zeros(n_samples - n_missing_samples,\n                                          dtype=np.bool),\n                                 np.ones(n_missing_samples,\n                                         dtype=np.bool)))\n    rng.shuffle(missing_samples)\n    missing_features = rng.randint(0, n_features, n_missing_samples)\n    X_missing = X_full.copy()\n    X_missing[np.where(missing_samples)[0], missing_features] = 0\n    y_missing = y_full.copy()\n\n    # Estimate the score after replacing missing values by 0\n    imputer = SimpleImputer(missing_values=0,\n                            strategy='constant',\n                            fill_value=0)\n    zero_impute_scores = get_scores_for_imputer(imputer, X_missing, y_missing)\n\n    # Estimate the score after imputation (mean strategy) of the missing values\n    imputer = SimpleImputer(missing_values=0, strategy=\"mean\")\n    mean_impute_scores = get_scores_for_imputer(imputer, X_missing, y_missing)\n\n    # Estimate the score after kNN-imputation of the missing values\n    imputer = KNNImputer(missing_values=0)\n    knn_impute_scores = get_scores_for_imputer(imputer, X_missing, y_missing)\n\n    # Estimate the score after iterative imputation of the missing values\n    imputer = IterativeImputer(missing_values=0,\n                               random_state=0,\n                               n_nearest_features=5,\n                               sample_posterior=True)\n    iterative_impute_scores = get_scores_for_imputer(imputer,\n                                                     X_missing,\n                                                     y_missing)\n\n    return ((full_scores.mean(), full_scores.std()),\n            (zero_impute_scores.mean(), zero_impute_scores.std()),\n            (mean_impute_scores.mean(), mean_impute_scores.std()),\n            (knn_impute_scores.mean(), knn_impute_scores.std()),\n            (iterative_impute_scores.mean(), iterative_impute_scores.std()))\n\n\nresults_diabetes = np.array(get_results(load_diabetes()))\nmses_diabetes = results_diabetes[:, 0] * -1\nstds_diabetes = results_diabetes[:, 1]\n\nresults_boston = np.array(get_results(load_boston()))\nmses_boston = results_boston[:, 0] * -1\nstds_boston = results_boston[:, 1]\n\nn_bars = len(mses_diabetes)\nxval = np.arange(n_bars)\n\nx_labels = ['Full data',\n            'Zero imputation',\n            'Mean Imputation',\n            'KNN Imputation',\n            'Iterative Imputation']\ncolors = ['r', 'g', 'b', 'orange', 'black']\n\n# plot diabetes results\nplt.figure(figsize=(12, 6))\nax1 = plt.subplot(121)\nfor j in xval:\n    ax1.barh(j, mses_diabetes[j], xerr=stds_diabetes[j],\n             color=colors[j], alpha=0.6, align='center')\n\nax1.set_title('Imputation Techniques with Diabetes Data')\nax1.set_xlim(left=np.min(mses_diabetes) * 0.9,\n             right=np.max(mses_diabetes) * 1.1)\nax1.set_yticks(xval)\nax1.set_xlabel('MSE')\nax1.invert_yaxis()\nax1.set_yticklabels(x_labels)\n\n# plot boston results\nax2 = plt.subplot(122)\nfor j in xval:\n    ax2.barh(j, mses_boston[j], xerr=stds_boston[j],\n             color=colors[j], alpha=0.6, align='center')\n\nax2.set_title('Imputation Techniques with Boston Data')\nax2.set_yticks(xval)\nax2.set_xlabel('MSE')\nax2.invert_yaxis()\nax2.set_yticklabels([''] * n_bars)\n\nplt.show()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.6.9"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}